package com.github.yyeerai.hybridserverapi.v1_20_1.api.forgelistener;

import com.github.yyeerai.hybridserverapi.common.interfaces.IForgeEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.IEventBus;
import org.bukkit.plugin.Plugin;

import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * ForgeEventImp 类实现了 IForgeEvent 接口，用于管理 Forge 事件监听器的注册和注销。
 */
public class ForgeEventImp implements IForgeEvent {

    // 已注册的监听器列表，使用同步列表以确保线程安全
    private static final List<ForgeListener<?>> registeredListeners = Collections.synchronizedList(new ArrayList<>());
    // 处理器映射，存储每个插件对应的监听器列表
    private static final Map<Plugin, List<ForgeListener<?>>> HandlerMap = new ConcurrentHashMap<>();
    // 日志记录器
    private static final Logger logger = Logger.getLogger(ForgeEventImp.class.getName());

    /**
     * 注册事件监听器
     *
     * @param plugin   插件实例
     * @param listener 监听器对象
     * @param eventBus 事件总线
     */
    @Override
    public void register(Plugin plugin, Object listener, Object eventBus) {
        // 获取监听器类中所有带有 @ForgeEventListener 注解的方法
        List<Method> listenerMethods = getAnnotatedMethods(listener.getClass());
        List<ForgeListener<?>> forgeListeners = new ArrayList<>();
        for (Method method : listenerMethods) {
            // 创建 ForgeListener 对象
            ForgeListener<?> forgeListener = createForgeListener(eventBus, listener, method);
            if (forgeListener == null) {
                logger.warning("无法创建ForgeListener，请检查方法签名是否正确");
                continue;  // 不要直接 return，继续注册其他监听器
            }
            // 注册监听器
            forgeListener.register();
            forgeListeners.add(forgeListener);
        }
        // 将插件和其对应的监听器列表存储到 HandlerMap 中
        if (plugin != null && !forgeListeners.isEmpty()) {
            HandlerMap.computeIfAbsent(plugin, k -> new ArrayList<>()).addAll(forgeListeners);
        }
    }

    /**
     * 创建 ForgeListener 对象
     *
     * @param eventBus 事件总线
     * @param listener 监听器对象
     * @param method   监听器方法
     * @return 创建的 ForgeListener 对象，如果方法签名不正确则返回 null
     */
    private ForgeListener<?> createForgeListener(Object eventBus, Object listener, Method method) {
        if (method == null) {
            return null;
        }
        // 获取方法上的 @ForgeEventListener 注解
        ForgeEventListener annotation = method.getAnnotation(ForgeEventListener.class);
        Class<?> eventClass = annotation.value();

        // 检查事件类是否是 Event 的子类
        if (!Event.class.isAssignableFrom(eventClass)) {
            logger.warning("事件类 " + eventClass.getName() + " 不是 Event 的子类");
            return null;
        }

        // 创建并返回 ForgeListener 对象
        return new ForgeListener<>((IEventBus) eventBus, (Class<? extends Event>) eventClass, event -> {
            try {
                method.invoke(listener, event);
            } catch (Exception e) {
                logger.log(Level.SEVERE, "事件处理方法调用失败", e);
            }
        }, annotation.priority());
    }

    /**
     * 获取类中所有带有 @ForgeEventListener 注解的方法
     *
     * @param aClass 类对象
     * @return 带有 @ForgeEventListener 注解的方法列表
     */
    private List<Method> getAnnotatedMethods(Class<?> aClass) {
        List<Method> methods = new ArrayList<>();
        for (Method method : aClass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(ForgeEventListener.class)) {
                methods.add(method);
            }
        }
        return methods;
    }

    /**
     * 注销所有已注册的监听器
     */
    @Override
    public void unregisterAll() {
        synchronized (registeredListeners) {
            Iterator<ForgeListener<?>> iterator = registeredListeners.iterator();
            while (iterator.hasNext()) {
                ForgeListener<?> listener = iterator.next();
                listener.unregister();
                iterator.remove();
            }
        }
    }

    /**
     * 注销指定插件的所有监听器
     *
     * @param plugin 插件实例
     */
    @Override
    public void unregisterAll(Plugin plugin) {
        List<ForgeListener<?>> listeners = HandlerMap.get(plugin);
        if (listeners != null) {
            synchronized (listeners) {
                Iterator<ForgeListener<?>> iterator = listeners.iterator();
                while (iterator.hasNext()) {
                    ForgeListener<?> listener = iterator.next();
                    listener.unregister();
                    iterator.remove();
                }
            }
            HandlerMap.remove(plugin);
        }
    }
}